#include<windows.h>
#include<conio.h>
int T, X ,Y, c, i, j, k, map[250] = { 0 }, node[28][4] = {
	-1,0,1,-11,10,0,-10,-9,11,-1,0,1,9,10,0,-10, -1,0,1,-9,10,11,0,-10,9,-1,0,1,
	10,0,-10,-11, 9,10,0,1,11,0,1,-10,9,10,0,1,11,0,1,-10, 10,11,-1,0,10,0,1,-9,
	10,11,-1,0,10,0,1,-9,-1,0,1,-10,10,0,1,-10,10,-1,0,1,10,-1,0,-10,20,10,0,-10,
	-1,0,1,2,20,10,0,-10,-1,0,1,2,10,11,0,1,10,11,0,1,10,11,0,1,10,11,0,1 };
int move(int* v, int l) {
	for (*v += l, i = 0; i < 4 && (j = (node[T][i] + 11) % 10 - 1 + X, 1); i++)
		if ((j < 0 || 9 < j || 24 < (node[T][i] + 11) / 10 - 1 + Y ||
			map[node[T][i] + Y * 10 + X]) && (*v -= l, 1))return 0;
	return 1;
}
void down() {
	if (move(&Y, 1) || Y < 2 && (exit(!_getch()), 0))return;
	for (i = 0; i < 4 && (map[node[T][i] + Y * 10 + X] = 1); i++);
	for (i = 250, k = 0; i >= 10 || (c = 0); i % 10 == 0 && (k = 0))
		if (--i, (k += map[i]) == 10)
			for (j = i + 9; j > 9 || (i += 10, 0); map[j] = map[j - 10], j--);
}
int main() {
	srand((unsigned)malloc(!system("mode con: cols=20 lines=25")));
	for (; c || (X = 4, Y = 1, T = rand() % 7 * 4, c = 1); down(), Sleep(150)) {
		if (_kbhit() && (c = _getch())) {
			if (c == 'w' || c == 'W')move(&T, (T % 4) < 3 ? 1 : -3);
			else if (c == 'd' || c == 'D')X < 9 && move(&X, 1);
			else if (c == 'a' || c == 'A')X > 0 && move(&X, -1);
			else if (c == 's' || c == 'S')down();
		}
		for (i = system("cls"); i < 4 && (map[node[T][i] + Y * 10 + X] = -1); i++);
		for (i = 0; i < 250; i++)_cputs(map[i] ? "[]" : "  "), map[i] += map[i] < 0;
	}
}

/*
33行俄罗斯方块, 1552字符, 实现了简单的功能;
AD移动, S下坠, W旋转, 某一行填满方块则消行, 当方块堆到顶层时游戏结束;
每轮循环都会下坠, 体验并不是很好, 局限于当时的技术只能这样了...
现在都已经到22行了, 无论是代码还是体验都比这个好很多
额外提及几点:
1. malloc()的返回值被忽略, 会不会造成内存泄漏?
这个其实没什么好担心的, 又不是在循环里执行, 程序结束都释放了
2. 此处的windows.h可换成stdlib.h
Sleep()换成_sleep()就行, 在vs会出现4996号错误, 屏蔽就行了
屏蔽4996号错误可使用下面的代码:
#pragma warning(disable:4996)
3. 关于移植到其他平台
conio.h并不属于标准库, 输出可以用stdio.h里的printf()
输入可能麻烦点, getch()和kbhit()可以自己用其他函数来实现
这方面网上有很多方法, 这里仅能提供一个游戏整体的思路

于2020.1.29上传, 2020.10.2补充说明
*/